package me.zhengjie.modules.system.service.impl;

import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.System;
import me.zhengjie.modules.system.repository.SystemRepository;
import me.zhengjie.modules.system.service.SystemService;
import me.zhengjie.modules.system.service.dto.SystemDto;
import me.zhengjie.modules.system.service.mapstruct.SystemMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * SystemServiceImpl
 *
 * @author guoyuan
 * @version 1.0.0
 * @since 1.0.0
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "system")
public class SystemServiceImpl implements SystemService {

    private final SystemRepository systemRepository;
    private final SystemMapper systemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(System resources) {
        final System existsSystem = systemRepository.findSystemBySystemNameEquals(resources.getSystemName());
        if (!Objects.isNull(existsSystem)) {
            throw new BadRequestException("系统[" + resources.getSystemName() + "]已存在");
        }
        resources.setSystemId(getSystemId());
        systemRepository.save(resources);
    }

    private int getSystemId() {
        final System first = systemRepository.findFirstByOrderBySystemIdDesc();
        int systemId;
        if (first == null) {
            systemId = 1;
        } else {
            systemId = first.getSystemId() + 1;
        }
        return systemId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<String> ids) {
        final List<System> allById = systemRepository.findAllByIdInOrderBySystemIdAsc(ids);
        if (allById.isEmpty()) {
            return;
        }
        final System first = allById.get(0);
        final Integer systemId = first.getSystemId();
        final Map<String, System> collect = systemRepository.findAllBySystemIdGreaterThanOrderBySystemIdAsc(systemId)
                .stream().collect(Collectors.toMap(System::getId, s -> s));
        for (System delete : allById) {
            collect.remove(delete.getId());
            systemRepository.delete(delete);
        }
        final List<System> systemList = new ArrayList<>(collect.values());
        if (!systemList.isEmpty()) {
            final System lastSystem = systemRepository.findFirstBySystemIdLessThanOrderBySystemIdDesc(systemId);
            Integer lastSystemId = 0;
            if (lastSystem != null) {
                lastSystemId = lastSystem.getSystemId();
            }
            for (System system : systemList) {
                lastSystemId += 1;
                system.setSystemId(lastSystemId);
            }
            systemRepository.saveAll(systemList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SystemDto resources) {
        final Optional<System> byId = systemRepository.findById(resources.getId());
        final String systemName = resources.getSystemName();
        if (!byId.isPresent()) {
            throw new BadRequestException("系统[" + systemName + "]不存在");
        }
        final System oldSystem = byId.get();
        if (!oldSystem.getSystemName().equals(systemName)) {
            final System existsSystem = systemRepository.findSystemBySystemNameEquals(systemName);
            if (!Objects.isNull(existsSystem)) {
                throw new BadRequestException("系统[" + systemName + "]已存在");
            }
        }
        final System system = systemMapper.toEntity(resources);
        system.setSystemId(oldSystem.getSystemId());
        systemRepository.save(system);
    }

    @Override
    public List<SystemDto> queryAll() {
        final List<System> systemId = systemRepository.findAll(Sort.by(Sort.Direction.DESC, "systemId"));
        if (systemId.isEmpty()) {
            return Lists.newArrayList();
        }
        return systemMapper.toDto(systemId);
    }
}
